package dslProgramGen.newArray;

import dslProgramGen.WhoPointToThisObjectCollection;
import utils.Utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static dslProgramGen.DslProgramGen.isGenJavaProgram;
import static dslProgramGen.newNormalObject.NewNormalObj.postProcessNewObjAssignToObjFieldOrArrayIndex;
import static dslProgramGen.util.DslProgramGenUtil.*;

public class NewArrayObj {
    /**
     * 新建数组对象DSL语句等号右边内容
     *
     * @param newArrayObjectType 新建数组对象类型
     * @param newArrayLength     新建数组最外层元素个数
     * @return 新建数组对象DSL语句等号右边内容
     */
    public static String genNewArrayObjEqualSignRightStatement(String newArrayObjectType, String newArrayLength) {
        String rightStatement = null;
        // 获得新建数组对象的维度
        int dimNum = getDimNumFromArrayObjectType(newArrayObjectType);
        // 获得elementType
        String elementType = getElementTypeFromArrayObjectType(newArrayObjectType);
        if (isGenJavaProgram) {
            // 如果直接输出的是Java程序
            // 构造等号右边的 []表达
            String squareBracket = "";
            for (int i = 0; i < dimNum - 1; i++) {
                squareBracket += "[]";
            }
            rightStatement = "new " + elementType + "[" + newArrayLength + "]" + squareBracket + ";";
        } else {
            // 如果输出的是DSL程序
            rightStatement = "NewArray(" + elementType + ", " + dimNum + ", " + newArrayLength + ");";
        }
        return rightStatement;
    }

    /**
     * 找到与最外层新建数组对象匹配的trace行
     *
     * @param outerObjectId           最外层新建数组对象id
     * @param currentProcessedLineNum 当前处理的trace行num
     * @param tracesList              一个TextNode的所有traces列表
     * @return 如果找到匹配的行，返回行号，否则，返回-1
     */
    public static int findMatchLineForOuterArray(String outerObjectId, int currentProcessedLineNum, List<String> tracesList) {
        for (int i = currentProcessedLineNum; i < tracesList.size(); i++) {
            String line = tracesList.get(i);
            // 获得这一行trace的操作名称
            String lineComand = Utils.RegularExpressionProcess(line, "\\[gc,heap\\s+\\] (.*?) (H|H1):");
            if (lineComand != null) {
                switch (lineComand) {
                    case "Put":
                    case "PutA":
                        // Put H1:0x0000000046cdf8bd, C1:Student, IS:true, H2:0x000000000f0c8a99, C2:Course, F:112, T:main, M:java/lang/module/Configuration.<init> (Ljava/util/List;Ljava/lang/module/Resolver;)V
                        // PutA H1:0x0000000046cdf8bd, C1:[[Ljava/lang/invoke/LambdaForm$Name;, H2:0x000000000f0c8a99, C2:[Ljava/lang/invoke/LambdaForm$Name;, O:0, T:main, M:java/lang/invoke/LambdaForm.<clinit> ()V
                        // 获得H2的id
                        String H2Id = Utils.RegularExpressionProcess(line, "H2:(.*?),");
                        if (H2Id.equals(outerObjectId)) {
                            // 表示该行就是与新建最外层数组对象匹配的行
                            return i;
                        }
                        break;
                    case "Add LR":
                    case "Return":
                        // Add LR H:0x000000004edde6e5, C:java/lang/ThreadGroup, T:main, R: NULL, M:java/lang/ThreadGroup.addUnstarted ()V
                        // Return H:0x000000001e80bfe8, C:java/lang/ThreadGroup, T:main
                        // 获得H的id
                        String HId = Utils.RegularExpressionProcess(line, "H:(.*?),");
                        if (HId.equals(outerObjectId)) {
                            // 表示该行就是与新建最外层数组对象匹配的行
                            return i;
                        }
                        break;
                    default:
                        // 还有可能为NewL，表示新建多维数组内部的数组对象
                        break;
                }
            }
        }
        // 该TextNode剩下的行都找不到与该新建最外层数组对象匹配的行，表示该新建数组对象是f(new array[2][3])模式
        return -1;
    }

    /**
     * 找到与新建lower数组对象trace匹配的trace行
     *
     * @param innerArrayObjectId      新建inner数组对象id
     * @param currentProcessedLineNum 当前处理的trace行num
     * @param tracesList              新建多维数组，inner数组对象所在的trace list
     * @return 如果找到匹配的行，返回序号，否则，返回-1（一般不会找不到）
     */
    public static int findMatchLineForInnerArray(String innerArrayObjectId, int currentProcessedLineNum, List<String> tracesList) {
        for (int i = currentProcessedLineNum; i < tracesList.size(); i++) {
            String line = tracesList.get(i);
            // 获得这一行trace的操作名称
            String lineComand = Utils.RegularExpressionProcess(line, "\\[gc,heap\\s+\\] (.*?) (H|H1):");
            if (lineComand != null) {
                switch (lineComand) {
                    case "PutA":
                        // Put H1:0x0000000046cdf8bd, C1:Student, IS:true, H2:0x000000000f0c8a99, C2:Course, F:112, T:main, M:java/lang/module/Configuration.<init> (Ljava/util/List;Ljava/lang/module/Resolver;)V
                        // PutA H1:0x0000000046cdf8bd, C1:[[Ljava/lang/invoke/LambdaForm$Name;, H2:0x000000000f0c8a99, C2:[Ljava/lang/invoke/LambdaForm$Name;, O:0, T:main, M:java/lang/invoke/LambdaForm.<clinit> ()V
                        // 获得H2的id
                        String H2Id = Utils.RegularExpressionProcess(line, "H2:(.*?),");
                        if (H2Id.equals(innerArrayObjectId)) {
                            // 表示该行就是与新建inner数组对象匹配的行
                            return i;
                        }
                        break;
                    default:
                        // 还有可能为NewL，表示新建多维数组内部的数组对象
                        break;
                }
            }
        }
        return -1;
    }

    /**
     * 在已新建最外层的多维数组对象的情况下，新建多维数组内部的数组对象
     *
     * @param lines                   新建多维数组内部的数组对象 的traces
     * @param dslMethodContentList    生成的DSL程序的函数体
     * @param objId2objExpressionsMap 指定对象id在DSL程序中可以怎样表示出来 <objId, expressions>
     * @param dslObjFieldToObjIdMap   给定DSL语句（对象.field 或 对象数组[index]），看看该DSL语句指向哪个对象Id，主要是帮助处理Put与PutA的trace，减少查询时间
     */
    public static void genNewLowerArrayObjInMultiArray(List<String> lines, List<String> dslMethodContentList,
                                                       Map<String, WhoPointToThisObjectCollection> objId2objExpressionsMap,
                                                       Map<String, String> dslObjFieldToObjIdMap) {
        List<Boolean> hasProcessedLineNumList = new ArrayList<>();
        // 初始化hasProcessedLineNumList为false，表示lines中的行都没有处理过
        for (int i = 0; i < lines.size(); i++) {
            hasProcessedLineNumList.add(false);
        }

        // 处理lines中的每一行
        for (int i = 0; i < lines.size(); i++) {
            if (!hasProcessedLineNumList.get(i)) {
                String currentLine = lines.get(i);
                // 这行内容没有被处理过，这行肯定以NewL开头
                // NewL H:0x000000001b5c2310, C:[[I, R:2, S:2, T:main
                // 获得NewL lower数组对象的H内容
                String lowerArrayHId = Utils.RegularExpressionProcess(currentLine, "H:(.*?),");
                // 获得NewL lower数组对象的类型
                String lowerArrayType = Utils.RegularExpressionProcess(currentLine, "C:(.*?),");
                lowerArrayType = renameClassNameReplaceSlashWithUnderlineAndRenameObjectClassName(lowerArrayType);
                // 获得NewL lower数组对象的元素个数
                String lowerArrayLength = Utils.RegularExpressionProcess(currentLine, "S:(.*?),");
                // 找到这个NewL匹配的PutA所在的行，H2为该lower数组对象的id
                int matchLineNumForInnerArray = findMatchLineForInnerArray(lowerArrayHId, i + 1, lines);
                // 获得与该NewL匹配的PutA行
                // PutA H1:0x00000000101c3833, C1:[[[I, H2:0x000000001b5c2310, C2:[[I, O:0, T:main, M:Test.main ([Ljava/lang/String;)V
                String matchLine = lines.get(matchLineNumForInnerArray);
                // 生成DSL语句 array[index] = new array[i][];
                genNewArrayObjAssignToArrayIndex(lowerArrayType, lowerArrayHId, lowerArrayLength, matchLine,
                        dslMethodContentList,
                        objId2objExpressionsMap,
                        dslObjFieldToObjIdMap);

                // 与该NewL trace行 match的行被处理了
                hasProcessedLineNumList.set(matchLineNumForInnerArray, true);
                hasProcessedLineNumList.set(i, true);
            }
        }

    }


    /**
     * 新建数组对象 赋值给A.field trace转DSL
     * 生成 A.field = new Student[i][]; DSL语句
     * field可能为静态字段也可能为实例字段
     *
     * @param newArrayObjectType      新建数组对象类型 [LStudent; [I   [Ljava/lang/Object;  [[LStudent;  [[[LStudent;  [[[I
     * @param newArrayObjectId        新建数组对象id
     * @param newArrayLength          新建数组对象元素个数
     * @param matchLine               与新建数组对象trace语句匹配的trace
     * @param isStatic                字段是否为静态字段
     * @param dslMethodContentList    生成的DSL程序的函数体
     * @param objId2objExpressionsMap 指定对象id在DSL程序中可以怎样表示出来 <objId, expressions>
     * @param dslObjFieldToObjIdMap   给定DSL语句（对象.field 或 对象数组[index]），看看该DSL语句指向哪个对象Id，主要是帮助处理Put与PutA的trace，减少查询时间
     */
    public static void genNewArrayObjAssignToObjField(String newArrayObjectType, String newArrayObjectId, String newArrayLength, String matchLine, boolean isStatic,
                                                      List<String> dslMethodContentList,
                                                      Map<String, WhoPointToThisObjectCollection> objId2objExpressionsMap,
                                                      Map<String, String> dslObjFieldToObjIdMap) {
        // 修改静态字段例子 Put H1:0x0000000046cdf8bd, C1:Student, IS:true, H2:0x000000000f0c8a99, C2:Course, F:112, T:main, M:java/lang/module/Configuration.<init> (Ljava/util/List;Ljava/lang/module/Resolver;)V
        // 修改实例字段例子 Put H1:0x000000003de64145, C1:java/lang/module/Configuration, IS:false, H2:0x000000001ecd979e, C2:java/util/ImmutableCollections$List12, F:12, T:main, M:java/lang/module/Configuration.<init> (Ljava/util/List;Ljava/lang/module/Resolver;)V
        String leftStatement;
        if (isStatic) {
            // 修改的是静态字段
            // 生成DSL语句，例如 Student.fields = new Student[i][];
            // 获得C1的类名称
            String c1ClassName = Utils.RegularExpressionProcess(matchLine, "C1:(.*?),");
            c1ClassName = renameClassNameReplaceSlashWithUnderlineAndRenameObjectClassName(c1ClassName);
            // 获得修改C1的字段名
            String fieldName = Utils.RegularExpressionProcess(matchLine, "F:(.*?),");

            // 生成DSL语句，例如 Student.fields = new Student[i][];
            leftStatement = c1ClassName + "." + fieldName;
            String rightStatement = genNewArrayObjEqualSignRightStatement(newArrayObjectType, newArrayLength);

            String dslStatement = genRefUpdateDslStatement(leftStatement, rightStatement);
            // 将该dsl语句加入函数体中
            dslMethodContentList.add(dslStatement);
        } else {
            // 修改的是实例字段
            // 生成DSL语句，例如 A.field = new Student[i][];
            // 获得H1的id
            String h1ObjId = Utils.RegularExpressionProcess(matchLine, "H1:(.*?),");
            // 获得修改H1的字段名
            String fieldName = Utils.RegularExpressionProcess(matchLine, "F:(.*?),");
            // 获得H1对象的dsl表示
            if (tryToGetDslExpressionOfObj(h1ObjId, objId2objExpressionsMap) == null) {
                return;
            }
            String h1DslExpression = getDslExpressionOfObj(h1ObjId, objId2objExpressionsMap);

            // 生成DSL语句，例如 A.field = new Student[i];
            leftStatement = h1DslExpression + "." + fieldName;
            String rightStatement = genNewArrayObjEqualSignRightStatement(newArrayObjectType, newArrayLength);
            String dslStatement = genRefUpdateDslStatement(leftStatement, rightStatement);
            // 将该dsl语句加入函数体中
            dslMethodContentList.add(dslStatement);
        }

        // 更新两个数据结构 objId2objExpressionsMap 与 dslObjFieldToObjIdMap
        postProcessNewObjAssignToObjFieldOrArrayIndex(leftStatement, newArrayObjectType, newArrayObjectId,
                objId2objExpressionsMap,
                dslObjFieldToObjIdMap);
    }

    /**
     * 新建数组对象 赋值给array[index] trace转DSL
     * 生成 array[index] = new Student[i][][]; DSL语句
     *
     * @param newArrayObjectType      新建数组对象类型 [LStudent; [I   [Ljava/lang/Object;  [[LStudent;  [[[LStudent;  [[[I
     * @param newArrayObjectId        新建数组对象id
     * @param newArrayLength          新建数组对象元素个数
     * @param matchLine               与新建数组对象trace语句匹配的trace
     * @param dslMethodContentList    生成的DSL程序的函数体
     * @param objId2objExpressionsMap 指定对象id在DSL程序中可以怎样表示出来 <objId, expressions>
     * @param dslObjFieldToObjIdMap   给定DSL语句（对象.field 或 对象数组[index]），看看该DSL语句指向哪个对象Id，主要是帮助处理Put与PutA的trace，减少查询时间
     */
    public static void genNewArrayObjAssignToArrayIndex(String newArrayObjectType, String newArrayObjectId, String newArrayLength, String matchLine,
                                                        List<String> dslMethodContentList,
                                                        Map<String, WhoPointToThisObjectCollection> objId2objExpressionsMap,
                                                        Map<String, String> dslObjFieldToObjIdMap) {
        // 修改数组index例子 PutA H1:0x0000000046cdf8bd, C1:[[Ljava/lang/invoke/LambdaForm$Name;, H2:0x000000000f0c8a99, C2:[Ljava/lang/invoke/LambdaForm$Name;, O:0, T:main, M:java/lang/invoke/LambdaForm.<clinit> ()V
        // 生成DSL语句，例如 array[index] = new Student[i][];
        // 获得H1的id
        String h1ObjId = Utils.RegularExpressionProcess(matchLine, "H1:(.*?),");
        // 获得修改H1的index
        String index = Utils.RegularExpressionProcess(matchLine, "O:(.*?),");
        // 获得H1对象的dsl表示
        if (tryToGetDslExpressionOfObj(h1ObjId, objId2objExpressionsMap) == null) {
            return;
        }
        String h1DslExpression = getDslExpressionOfObj(h1ObjId, objId2objExpressionsMap);

        // 生成DSL语句，例如 array[index] = new Student[i][];
        String leftStatement = h1DslExpression + "[" + index + "]";
        String rightStatement = genNewArrayObjEqualSignRightStatement(newArrayObjectType, newArrayLength);
        String dslStatement = genRefUpdateDslStatement(leftStatement, rightStatement);
        // 将该dsl语句加入函数体中
        dslMethodContentList.add(dslStatement);

        // 更新两个数据结构 objId2objExpressionsMap 与 dslObjFieldToObjIdMap
        postProcessNewObjAssignToObjFieldOrArrayIndex(leftStatement, newArrayObjectType, newArrayObjectId,
                objId2objExpressionsMap,
                dslObjFieldToObjIdMap);

    }


    /**
     * 新建数组对象 赋值给local root trace转DSL
     * 生成 Student[][] stu = new Student[i][]; 或 stu = new Student[i][]; DSL语句
     *
     * @param newArrayObjectType      新建数组对象类型 [LStudent; [I   [Ljava/lang/Object;  [[LStudent;  [[[LStudent;  [[[I
     * @param newArrayObjectId        新建数组对象id
     * @param newArrayLength          新建数组对象元素个数
     * @param matchLine               与新建数组对象trace语句匹配的trace
     * @param dslMethodContentList    生成的DSL程序的函数体
     * @param objId2objExpressionsMap 指定对象id在DSL程序中可以怎样表示出来 <objId, expressions>
     * @param classTypeAndNumMap      local root命名的辅助结构， 对于新建local root例如Student stu，如何命名stu，当前采用 "student"+num的方式表示
     */
    public static void genNewArrayObjAssignToLocalRoot(String newArrayObjectType, String newArrayObjectId, String newArrayLength, String matchLine,
                                                       List<String> dslMethodContentList,
                                                       Map<String, WhoPointToThisObjectCollection> objId2objExpressionsMap,
                                                       Map<String, Long> classTypeAndNumMap) {
        // 新建local root例子 Add LR H:0x000000004edde6e5, C:java/lang/ThreadGroup, T:main, R: NULL, M:java/lang/ThreadGroup.addUnstarted ()V
        // 给local root赋值例子 Add LR H:0x000000000d716361, C:java/lang/Class, T:main, R:0x000000004459eb14, M:java/util/ImmutableCollections$MapN.<init> ([Ljava/lang/Object;)V

        // 首先获得R部分内容
        String contentOfR = Utils.RegularExpressionProcess(matchLine, "R: ?(.*?),");
        if (contentOfR.equals("NULL")) { // 表示新增一个gc root
            // 生成DSL语句，例如 Student[][] stu = new Student[i][];
            // 如果要创建local root，先获得local root的序号
            long prNum = getLocalRootNum(newArrayObjectType, classTypeAndNumMap);
            // 获得其element类型
            String elementType = getElementTypeFromArrayObjectType(newArrayObjectType);
            // 获得新建数组对象的维度
            int dimNum = getDimNumFromArrayObjectType(newArrayObjectType);
            // 构造等号右边的 []表达 squareBracket比数组维度少一个[]
            String squareBracket = "";
            for (int i = 0; i < dimNum - 1; i++) {
                squareBracket += "[]";
            }

            // 组成local root的全名 小写(elementType)_array_维度_prNum
            String prVariableName = elementType.toLowerCase() + "_array_"+ dimNum + "_" + prNum;
            String leftStatement = elementType + "[]" + squareBracket + " " + prVariableName;
            String rightStatement = genNewArrayObjEqualSignRightStatement(newArrayObjectType, newArrayLength);
            String dslStatement = leftStatement + " = " + rightStatement;
            // 将该dsl语句加入函数体中
            dslMethodContentList.add(dslStatement);

            // 将newObjectId添加到objId2objExpressionsMap
            WhoPointToThisObjectCollection whoPointToThisObjectCollection = new WhoPointToThisObjectCollection(newArrayObjectType, newArrayObjectId);
            whoPointToThisObjectCollection.lrAndPrPointToThisObjectList.add(prVariableName);
            objId2objExpressionsMap.put(newArrayObjectId, whoPointToThisObjectCollection);
        } else { // 表示修改一个gc root
            // 生成DSL语句，例如 stu = new Student[i][];
            // R的内容就是之前local root指向的对象id，获得local root的dsl表示
            String leftStatement = objId2objExpressionsMap.get(contentOfR).lrAndPrPointToThisObjectList.get(0);

            String rightStatement = genNewArrayObjEqualSignRightStatement(newArrayObjectType, newArrayLength);
            String dslStatement = leftStatement + " = " + rightStatement;
            // 将该dsl语句加入函数体中
            dslMethodContentList.add(dslStatement);

            // 将newObjectId添加到objId2objExpressionsMap
            WhoPointToThisObjectCollection whoPointToThisObjectCollection = new WhoPointToThisObjectCollection(newArrayObjectType, newArrayObjectId);
            whoPointToThisObjectCollection.lrAndPrPointToThisObjectList.add(leftStatement);
            objId2objExpressionsMap.put(newArrayObjectId, whoPointToThisObjectCollection);
            // 从谁指向R的local root列表中移除leftStatement
            objId2objExpressionsMap.get(contentOfR).lrAndPrPointToThisObjectList.remove(0);
        }
    }


    /**
     * 新建数组对象 然后Return该新对象 trace转DSL
     * 本来应该生成 Return new Student[i][]; DSL语句，为简化该过程，分为两步
     * 1. 将new Student[i][]赋值给临时gc root 例如 Student[][] tempStu = new Student[i][];
     * 2. 后续处理Return语句的时候 产生 Return tempStu,并且从谁指向新对象的 newForReturnTempLocalRootList列表中删除 tempStu
     * 该函数主要是产生临时gc root赋值语句，即第一步工作
     *
     * @param newArrayObjectType      新建数组对象类型 [LStudent; [I   [Ljava/lang/Object;  [[LStudent;  [[[LStudent;  [[[I
     * @param newArrayObjectId        新建数组对象id
     * @param newArrayLength          新建数组对象元素个数
     * @param dslMethodContentList    生成的DSL程序的函数体
     * @param objId2objExpressionsMap 指定对象id在DSL程序中可以怎样表示出来 <objId, expressions>
     * @param classTypeAndNumMap      local root命名的辅助结构， 对于新建local root例如Student stu，如何命名stu，当前采用 "student"+num的方式表示
     */
    public static void genNewArrayObjAssignToTempLocalRootForReturn(String newArrayObjectType,
                                                                    String newArrayObjectId,
                                                                    String newArrayLength,
                                                                    List<String> dslMethodContentList,
                                                                    Map<String, WhoPointToThisObjectCollection> objId2objExpressionsMap,
                                                                    Map<String, Long> classTypeAndNumMap) {
        // 生成DSL语句，例如 Student[][] tempStu = new Student[i][];
        // 如果要创建local root，先获得local root的序号
        long prNum = getLocalRootNum(newArrayObjectType, classTypeAndNumMap);
        // 获得其element类型
        String elementType = getElementTypeFromArrayObjectType(newArrayObjectType);
        // 获得新建数组对象的维度
        int dimNum = getDimNumFromArrayObjectType(newArrayObjectType);
        // 构造等号右边的 []表达 squareBracket比数组维度少一个[]
        String squareBracket = "";
        for (int i = 0; i < dimNum - 1; i++) {
            squareBracket += "[]";
        }

        // 组成临时local root的全名 小写(类型)_array_tempLocalRootForReturn_prNum
        String prVariableName = elementType.toLowerCase() + "_array_tempLocalRootForReturn_" + prNum;
        String leftStatement = elementType + "[]" + squareBracket + " " + prVariableName;
        String rightStatement = genNewArrayObjEqualSignRightStatement(newArrayObjectType, newArrayLength);
        String dslStatement = leftStatement + " = " + rightStatement;
        // 将该dsl语句加入函数体中
        dslMethodContentList.add(dslStatement);

        // 将newObjectId添加到objId2objExpressionsMap，只是这里添加到的是newForReturnTempLocalRootList
        WhoPointToThisObjectCollection whoPointToThisObjectCollection = new WhoPointToThisObjectCollection(newArrayObjectType, newArrayObjectId);
        whoPointToThisObjectCollection.newForReturnTempLocalRootList.add(prVariableName);
        objId2objExpressionsMap.put(newArrayObjectId, whoPointToThisObjectCollection);
    }

    /**
     * 新建数组对象 如果是多维数组对象则为最外层的数组对象 然后将该新对象传给函数 trace转DSL
     * 本来应该生成 f(new Student[i][]); 或 f(new Student[i]); DSL语句，为简化该过程，分为两步
     * 1. 将new Student[i][] 或 new Student[i]赋值给临时gc root 例如 Student[][] tempStu = new Student[i][]; 或 Student[] tempStu = new Student[i];
     * 2. 后续处理函数调用语句的时候 产生 f(tempStu),并且从谁指向新对象的 newForMethodParameterTempLocalRootList列表中删除 tempStu，然后将产生tempStu=null语句
     * 该函数主要是产生临时gc root赋值语句，即第一步工作
     *
     * @param newArrayObjectType      新建数组对象类型 [LStudent; [I [Ljava/lang/Object; [[[LStudent; [[[I
     * @param newArrayObjectId        新建数组对象id
     * @param newArrayLength          新建数组对象元素个数
     * @param dslMethodContentList    生成的DSL程序的函数体
     * @param objId2objExpressionsMap 指定对象id在DSL程序中可以怎样表示出来 <objId, expressions>
     * @param classTypeAndNumMap      local root命名的辅助结构， 对于新建local root例如Student[] stu，如何命名stu
     */
    public static void genNewArrayObjAssignToTempLocalRootForMethodParameter(String newArrayObjectType,
                                                                             String newArrayObjectId,
                                                                             String newArrayLength,
                                                                             List<String> dslMethodContentList,
                                                                             Map<String, WhoPointToThisObjectCollection> objId2objExpressionsMap,
                                                                             Map<String, Long> classTypeAndNumMap) {
        // 生成DSL语句，例如 Student[] tempStuArray = new Student[i];
        // 如果要创建local root，先获得local root的序号
        long prNum = getLocalRootNum(newArrayObjectType, classTypeAndNumMap);
        // newArrayObjectType可能为 [LStudent; [I [Ljava/lang/Object; [[[LStudent; [[[I
        // 获得其element类型 对于上面的分别为 Student int java/lang/Object Student int
        String elementType = getElementTypeFromArrayObjectType(newArrayObjectType);

        // 组成临时local root的全名 小写(elementType)_array_tempLocalRootForMethodParameter_prNum
        String prVariableName = elementType.toLowerCase() + "_array_tempLocalRootForMethodParameter_" + prNum;
        // 获得数组的维度
        int dimNum = getDimNumFromArrayObjectType(newArrayObjectType);
        String squareBrackets = ""; // 表示方括号比原来维度少1个[]，原来假如是三维数组，这里的表示为两个方括号 [][]
        for (int i = 0; i < dimNum - 1; i++) {
            squareBrackets += "[]";
        }
        String leftStatement = elementType + squareBrackets + "[]" + " " + prVariableName;
        String rightStatement = genNewArrayObjEqualSignRightStatement(newArrayObjectType, newArrayLength);
        String dslStatement = leftStatement + " = " + rightStatement;
        // 将该dsl语句加入函数体中
        dslMethodContentList.add(dslStatement);

        // 将newArrayObjectId添加到objId2objExpressionsMap，只是这里添加到的是newForMethodParameterTempLocalRootList
        WhoPointToThisObjectCollection whoPointToThisObjectCollection = new WhoPointToThisObjectCollection(newArrayObjectType, newArrayObjectId);
        whoPointToThisObjectCollection.newForMethodParameterTempLocalRootList.add(prVariableName);
        objId2objExpressionsMap.put(newArrayObjectId, whoPointToThisObjectCollection);
    }

}
